package ru.urfc.portal.developer_tasks;

import java.util.List;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.transaction.UserTransaction;

import junit.framework.TestCase;

import org.hamcrest.Matcher;
import org.junit.Assert;

import ru.urfc.portal.dao.BasePersistence;
import ru.urfc.portal.dao.Paging;
import ru.urfc.portal.dao.SpectrId;
import ru.urfc.portal.dao.filter.Filter;
import ru.urfc.portal.dao.impl.BaseUtil;
import ru.urfc.portal.exceptions.UserGetItemException;
import ru.urfc.portal.model.Client;
import ru.urfc.portal.model.Branch;
import ru.urfc.portal.model.SysObject;
import ru.urfc.portal.model.accounting.Contragent;
import ru.urfc.portal.ui.client.Constants;

public class BaseTestEjb extends TestCase implements BasePersistence, Constants {
	
	@Resource UserTransaction userTransaction;
	@EJB BasePersistence basePersistence;

	private boolean expectedUserGetItemException = false;

	public Client findClient(String contragentName) {
		Contragent contragent = exactlyOne(find(Branch.SVERD, Contragent.class, "name", contragentName));
		return exactlyOne(find(Client.class, "contragentId", contragent.getId()));
	}
	
	static public void assertEquals(long expected, Long actual) {
		assertEquals(new Long(expected), actual);
	}
	
	protected void setExpectedUserGetItemException() {
		this.expectedUserGetItemException  = true;
	}
	
	@Override
	protected void runTest() throws Throwable {
		try {
			super.runTest();
			if (expectedUserGetItemException) {
				fail("UserGetItemException should be thrown");
			}
		} catch (RuntimeException e) {
			if (expectedUserGetItemException &&
					e.getCause() != null && e.getCause().getCause() != null &&
					e.getCause().getCause() instanceof UserGetItemException) {
				return; // ok
			}				
			throw e;
		}
	}
	
	@Override
	public void runBare() throws Throwable {
		try {
			userTransaction.begin();
			super.runBare();
		} finally {
			userTransaction.rollback();
		}
	}
	
	public static <T> void assertThat(T actual, Matcher<T> matcher) {
		Assert.assertThat(actual, matcher);
	}
	
	public static <T> void assertThat(String reason, T actual, Matcher<T> matcher) {
		Assert.assertThat(reason, actual, matcher);
	}		
	
	public <T> T oneOrNull(List<T> list) {
		return BaseUtil.oneOrNull(list);
	}
	
	public <T> T exactlyOne(List<T> list) {
		return BaseUtil.exactlyOne(list);
	}

	@Override
	public <T> T findById(Class<T> klass, SpectrId spectrId) {
		return basePersistence.findById(klass, spectrId);
	}
	
	@Override
	public <T> T findById(Class<T> klass, Long id) {
		return basePersistence.findById(klass, id);
	}

	@Override
	public <T> T persist(T entity) {
		return basePersistence.persist(entity);
	}

	@Override
	public <T> void delete(Class<T> klass, String fieldName, Object value) {
		basePersistence.delete(klass, fieldName, value);
	}
	
	@Override
	public <T> void delete(Class<T> klass, Long id) {
		basePersistence.delete(klass, id);
	}

	@Override
	public void delete(SysObject entity) {
		basePersistence.delete(entity);
	}
	
	@Override
	public <T> List<T> find(Class<T> klass, String fieldName, Object value) {
		return basePersistence.find(klass, fieldName, value);
	}
	
	@Override
	public <T> List<T> find(Branch branch, Class<T> klass, String fieldName, Object value) {
		return basePersistence.find(branch, klass, fieldName, value);
	}
	
	@Override
	public <T> List<T> find(Class<T> klass, Filter filter) {
		return basePersistence.find(klass, filter);
	}
	
	@Override
	public <T> List<T> find(Branch branch, Class<T> klass, Filter filter) {
		return basePersistence.find(branch, klass, filter);
	}
	
	@Override
	public <T> List<T> findWhere(Branch branch, Class<T> klass, String expression, String orderBy, Paging paging, Object... parameners) {
		return basePersistence.findWhere(branch, klass, expression, orderBy, paging, parameners);
	}

	@Override
	public void detach(SysObject ... entities) {
		basePersistence.detach(entities);
	}

	@Override
	public void flush() {
		basePersistence.flush();
	}
	
}
